package com.fds.demo.alipay.utils;

import com.alipay.api.AlipayApiException;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.fds.demo.alipay.config.AliPayConf;
import com.fds.demo.alipay.config.AliPcPayParam;
import org.springframework.beans.BeanUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @author: fds
 * @date: 2019/8/29
 * @description: 支付宝支付工具类
 */
public class AliPayUtils {

    /**
     * 空参构造.
     */
    private AliPayUtils() { }

    /**
     * pc支付service.
     * @param response 响应体，返回form表单数据
     * @param aliPcPayParam 支付参数
     * @throws AlipayApiException
     * @throws IOException
     */
    public static void  pcPay(final HttpServletResponse response, final AliPayConf aliPayConf,
                      final AliPcPayParam aliPcPayParam)
            throws AlipayApiException, IOException {

        AlipayTradePagePayModel model = new AlipayTradePagePayModel();
        BeanUtils.copyProperties(aliPcPayParam, model);

        // 销售产品码，与支付宝签约的产品码名称。注：目前仅支持FAST_INSTANT_TRADE_PAY
        model.setProductCode("FAST_INSTANT_TRADE_PAY");

        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        request.setBizModel(model);
        request.setNotifyUrl(aliPcPayParam.getNotifyUrl());
        request.setReturnUrl(aliPcPayParam.getReturnUrl());
        // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        // 调用RSA签名方式
        CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
        certAlipayRequest.setServerUrl(aliPayConf.getServerUrl());
        certAlipayRequest.setAppId(aliPayConf.getAppId());
        certAlipayRequest.setPrivateKey(aliPayConf.getPrivateKey());
        certAlipayRequest.setFormat("json");
        certAlipayRequest.setCharset("utf-8");
        certAlipayRequest.setSignType("RSA2");
        certAlipayRequest.setCertPath(aliPayConf.getAppPublicCertPath());
        certAlipayRequest.setAlipayPublicCertPath(aliPayConf.getAliPayPublicCertPath());
        certAlipayRequest.setRootCertPath(aliPayConf.getAliPayRootCert());
        DefaultAlipayClient aliPayClient = new DefaultAlipayClient(certAlipayRequest);

        String form = aliPayClient.pageExecute(request).getBody();
        response.setContentType("text/html;charset=utf-8");
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write(form);
        response.getWriter().flush();
        response.getWriter().close();
    }

    /**
     * 将异步通知的参数转化为Map.
     * @param request {HttpServletRequest}
     * @return 转化后的Map
     */
    public static Map<String, String> toMap(final HttpServletRequest request) {
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = iter.next();
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        return params;
    }

    /**
     * 验签支付宝通知.
     * @param params 校验参数
     * @param publicCertPath 支付宝公钥证书位置
     * @return Boolean
     * @throws AlipayApiException 异常
     */
    public static Boolean verifyResult(final Map<String, String> params, final String publicCertPath) throws AlipayApiException {
        // 获取支付宝GET过来反馈信息
        return AlipaySignature.rsaCertCheckV1(params, publicCertPath, "utf-8", "RSA2");
    }
}
